home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyc (Python 2.6) '''Mouse review mode.''' __id__ = '$Id: mouse_review.py 4221 2008-09-15 08:11:23Z wwalker $' __version__ = '$Revision: 4221 $' __date__ = '$Date: 2008-09-15 04:11:23 -0400 (Mon, 15 Sep 2008) $' __copyright__ = 'Copyright (c) 2008 Eitan Isaacson' __license__ = 'LGPL' import debug try: import wnck _mouseReviewCapable = True except: debug.println(debug.LEVEL_WARNING, 'Python module wnck not found, mouse review not available.') _mouseReviewCapable = False import gtk import gobject import orca import pyatspi import speech import braille import settings class BoundingBox: '''A bounding box, currently it is used to test if a given point is inside the bounds of the box. ''' def __init__(self, x, y, width, height): '''Initialize a bounding box. Arguments: - x: Left border of box. - y: Top border of box. - width: Width of box. - height: Height of box. ''' (self.x, self.y, self.width, self.height) = (x, y, width, height) def isInBox(self, x, y): '''Test if a given point is inside a box. Arguments: - x: X coordinate. - y: Y coordinate. Returns True if point is inside box. ''' if x <= x: pass elif x <= self.x + self.width: if y <= y: return y <= self.y + self.height y <= y return y class _WordContext: '''A word on which the mouse id hovering above. This class should have enough info to make it unique, so we know when we have left the word. ''' def __init__(self, word, acc, start, end): '''Initialize a word context. Arguments: - word: The string of the word we are on. - acc: The accessible object that contains the word. - start: The start offset of the word in the text. - end: The end offset of the word in the text. ''' self.word = word self.acc = acc self.start = start self.end = end def __cmp__(self, other): '''Compare two word contexts, if they refer to the same word, return 0. Otherwise return 1 ''' if other is None: return 1 if self.word == other.word and self.acc == other.acc and self.start == other.start: pass return int(not (self.end == other.end)) class _ItemContext: '''An _ItemContext holds all the information of the item we are currently hovering above. If the accessible supports word speaking, we also store a word context here. ''' def __init__(self, x = 0, y = 0, acc = None, frame = None, app = None, script = None): """Initialize an _ItemContext with all the information we have. Arguments: - x: The X coordinate of the pointer. - y: The Y coordinate of the pointer. - acc: The end-node accessible at that coordinate. - frame: The top-level frame below the pointer. - app: The application the pointer is hovering above. - script: The script for the context's application. """ self.acc = acc self.frame = frame self.app = app self.script = script self.word_ctx = self._getWordContext(x, y) def _getWordContext(self, x, y): """If the context's accessible supports it, retrieve the word we are currently hovering above. Arguments: - x: The X coordinate of the pointer. - y: The Y coordinate of the pointer. Returns a _WordContext of the current word, or None. """ if not (self.script) or not self.script.speakWordUnderMouse(self.acc): return None (word, start, end) = self.script.getWordAtCoords(self.acc, x, y) return _WordContext(word, self.acc, start, end) class MouseReviewer: '''Main class for the mouse-review feature. ''' def __init__(self): '''Initalize a mouse reviewer class. ''' if not _mouseReviewCapable: return None wnck_screen = wnck.screen_get_default() self.active = False self._currentMouseOver = _ItemContext() self._oldMouseOver = _ItemContext() self._lastReportedCoord = None def toggle(self, on = None): '''Toggle mouse reviewing on or off. Arguments: - on: If set to True or False, explicitly toggles reviewing on or off. ''' if not _mouseReviewCapable: return None if on is None: on = not (self.active) if on and not (self.active): pyatspi.Registry.registerEventListener(self._onMouseMoved, 'mouse:abs') elif not on and self.active: pyatspi.Registry.deregisterEventListener(self._onMouseMoved, 'mouse:abs') self.active = on def _onMouseMoved(self, event): '''Callback for "mouse:abs" AT-SPI event. We will check after the dwell delay if the mouse moved away, if it didn\'t we will review the component under it. Arguments: - event: The event we recieved. ''' if settings.mouseDwellDelay: gobject.timeout_add(settings.mouseDwellDelay, self._mouseDwellTimeout, event.detail1, event.detail2) else: self._mouseDwellTimeout(event.detail1, event.detail2) def _mouseDwellTimeout(self, prev_x, prev_y): '''Dwell timout callback. If we are still dwelling, review the component. Arguments: - prev_x: Previuos X coordinate of mouse pointer. - prev_y: Previuos Y coordinate of mouse pointer. ''' display = gtk.gdk.Display(gtk.gdk.get_display()) (screen, x, y, flags) = display.get_pointer() if abs(prev_x - x) <= settings.mouseDwellMaxDrift and abs(prev_y - y) <= settings.mouseDwellMaxDrift and not ((x, y) == self._lastReportedCoord): self._lastReportedCoord = (x, y) self._reportUnderMouse(x, y) return False def _reportUnderMouse(self, x, y): '''Report the element under the given coordinates: Arguments: - x: X coordinate. - y: Y coordinate. ''' current_element = self._getContextUnderMouse(x, y) if not current_element: return None self._currentMouseOver = current_element self._oldMouseOver = self._currentMouseOver output_obj = [] if current_element.acc.getRole() in (pyatspi.ROLE_MENU_ITEM, pyatspi.ROLE_COMBO_BOX) and current_element.acc.getState().contains(pyatspi.STATE_SELECTED): return None if (self._currentMouseOver.acc != self._oldMouseOver.acc or settings.mouseDwellDelay > 0) and not (self._currentMouseOver.word_ctx): output_obj.append(self._currentMouseOver.acc) if self._currentMouseOver.word_ctx: if self._currentMouseOver.word_ctx != self._oldMouseOver.word_ctx: output_obj.append(self._currentMouseOver.word_ctx.word) self._outputElements(output_obj) return False def _outputElements(self, output_obj): '''Output the given elements. TODO: Now we are mainly using WhereAmI, we might need to find out a better, less verbose output method. Arguments: - output_obj: A list of objects to output, could be accessibles and text. ''' if output_obj: speech.stop() for obj in output_obj: if obj is None: continue if isinstance(obj, str): speech.speak(obj) braille.displayMessage(obj) continue speech.speakUtterances(self._currentMouseOver.script.speechGenerator.getSpeech(obj, False)) self._currentMouseOver.script.updateBraille(obj) def _getZOrder(self, frame_name): '''Determine the stack position of a given window. Arguments: - frame_name: The name of the window. Returns position of given window in window-managers stack. ''' wnck_screen = wnck.screen_get_default() window_order = [ w.get_name() for w in wnck_screen.get_windows_stacked() ] return window_order.index(frame_name) def _getContextUnderMouse(self, x, y): '''Get the context under the mouse. Arguments: - x: X coordinate. - y: Y coordinate. Returns _ItemContext of the component under the mouse. ''' desktop = pyatspi.Registry.getDesktop(0) top_window = [ None, -1] for app in desktop: if not app: continue script = orca.getScriptForApp(app) if not script: continue for frame in app: if not frame: continue acc = script.getComponentAtDesktopCoords(frame, x, y) if acc: try: z_order = self._getZOrder(frame.name) except ValueError: try: if acc.queryComponent().getLayer() == pyatspi.LAYER_POPUP: return _ItemContext(x, y, acc, frame, app, script) if z_order > top_window[-1]: top_window = [ _ItemContext(x, y, acc, frame, app, script), z_order] z_order > top_window[-1] return top_window[0] if gtk.gdk.display_get_default(): mouse_reviewer = MouseReviewer() else: raise RuntimeError('Cannot initialize mouse review, no display') def toggle(script = gtk.gdk.display_get_default(), event = None): ''' Toggle the reviewer on or off. Arguments: - script: Given script if this was called as a keybinding callback. - event: Given event if this was called as a keybinding callback. ''' mouse_reviewer.toggle()